/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights
 * reserved. <a>http://www.cqcis.com</a>
 */
package com.cqcis.uip.base.framework.core;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.mina.common.IoSession;
import org.osgi.framework.Bundle;

import com.cqcis.uip.base.framework.FrameworkConstants;
import com.cqcis.uip.base.framework.base.adaptor.AbstractSocketService;
import com.cqcis.uip.base.framework.common.InterfaceLog;
import com.cqcis.uip.base.framework.common.Role;
import com.cqcis.uip.base.framework.common.TaskRecord;
import com.cqcis.uip.base.framework.common.TaskRepository;
import com.cqcis.uip.base.framework.utils.TimeUtil;
import com.cqcis.uip.base.logadaptor.LogConfiguration;

/**
 * 服务属性
 * 
 * @author huangmy
 * @date 2008-3-16
 */
public class RegisteredServiceProperty {
	private Collection<Endpoint> endpoints; // 端点
	private String id; // ID
	private String name; // 名称
	private Role role; // 角色
	private LogConfiguration logConfig; // 日志配置
	private String startTime; // 启动时间
	private RegisteredService rs;
	private Bundle bundle;
	
	// ----- Task计数 ------ //
	private TaskRecord taskRecord = new TaskRecord(); // 任务处理记录	
		
	public void setEndpoints(Collection<Endpoint> endpoints) {
		this.endpoints = endpoints;
	}

	public void setId(String id) {
		this.id = id;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setLogConfig(LogConfiguration logConfig) {
		this.logConfig = logConfig;
	}

	public Collection<Endpoint> getEndpoints() {
		return endpoints;
	}

	public String getId() {
		return id;
	}

	public String getName() {
		return name;
	}

	public LogConfiguration getLogConfig() {
		return logConfig;
	}
	
	public Role getRole() {
		return role;
	}

	public void setRole(Role role) {
		this.role = role;
	}

	@Override
	public String toString() {
		StringBuffer buffer = new StringBuffer();
		String ets = "";
		for (Endpoint e : endpoints) {
			ets = ets + e + "  ";
		}
		
		buffer.append("[URI]       ").append(ets).append("\n")
		      .append("[ID]        ").append(id).append("\n")
		      .append("[CONTROLID] ").append(bundle.getBundleId()).append("\n")
		      .append("[NAME]      ").append(name).append("\n")
		      .append("[ROLE]      ").append(role).append("\n")
		      .append("[LOG DIR]   ").append(logConfig.getDirname());
		if (rs != null && rs.getAttributes().getAttribute(FrameworkConstants.STREAM_LOG_NOT_WRITED) != null) {
			buffer.append("  ---- WARN: STREAMLOG CLOSED ----");
		}
		
		buffer.append("\n")
		      .append("[LOG LEVEL] ").append(logConfig.getLevel()).append("\n")
		      .append("[STARTTIME] ").append(startTime).append("\n");
		
		return buffer.toString();
	}
	
	/**
	 * 任务计数
	 * 
	 * @return
	 */
	public String getTaskRecordStr() {
		StringBuffer buffer = new StringBuffer();
		
		TaskRepository sendTaskRepository = null; // 发送任务记录
		TaskRepository recvTaskRepository = null; // 接收任务记录
		
		if (taskRecord != null) {
			sendTaskRepository = taskRecord.getSendTaskRepository();
			recvTaskRepository = taskRecord.getRecvTaskRepository();
		}
		
		if (sendTaskRepository != null) {
			buffer.append("SEND>> ").append("\n\t").append(formatTaskReposity(sendTaskRepository)).append("\n");
		}
		
		if (recvTaskRepository != null) {
			buffer.append("RECV>> ").append("\n\t").append(formatTaskReposity(recvTaskRepository)).append("\n");			
		}
		
		buffer.append("TRAFFIC>> ").append("\n\t")
		      .append(String.format("CAPACITY: %4d, SIZE: %4d, ACCEPTABLE: %4d", rs.getWaitTaskMax(), rs.getWaitTaskMax() - rs.acceptable(), rs.acceptable())).append("\n");
		
		return buffer.toString();
	}
	
	private static String formatTaskReposity(TaskRepository taskRepository) {
		return String.format("TOTAL: %6d, WAIT: %6d, SUCCESS: %6d, \n\tERROR: %6d, ERROR PLATFORM: %6d, ERROR SERVICE: %6d, \n\tLASTMODIFY: %s", 
				taskRepository.getTotal(), taskRepository.getWait(), taskRepository.getSuccess(),
				taskRepository.getError(), taskRepository.getErrorPlatform(), taskRepository.getErrorService(), 
				TimeUtil.getTimeStr(taskRepository.getLastModifyDate().getTime()));
	}
	
	/**
	 * 去除重复的数据
	 * 
	 * @param rsps
	 * @return
	 */
	private static Collection<RegisteredServiceProperty> preProcessRegisteredServicePropertyList(Collection<RegisteredServiceProperty> rsps) {		
		Map<Endpoint, RegisteredServiceProperty> maps = new HashMap<Endpoint, RegisteredServiceProperty>();
		for (RegisteredServiceProperty rsp : rsps) {
			Collection<Endpoint> es = rsp.getEndpoints();
			for (Endpoint e : es) {
				maps.put(e, rsp);
			}
		}
		
		Map<String, RegisteredServiceProperty> rspsNow = new HashMap<String, RegisteredServiceProperty>();		
		Collection<RegisteredServiceProperty> props = maps.values();		
		for (RegisteredServiceProperty rsp : props) {
			rspsNow.put(String.valueOf(rsp.getBundle().getBundleId()), rsp);
		}
		
		return rspsNow.values();
	}
	
	/**
	 * 生成描述
	 * 
	 * @param rsps
	 * @param lined
	 * @return
	 */
	public static String toString(Collection<RegisteredServiceProperty> rsps, boolean lined) {
		// 去掉重复的服务属性
		rsps = preProcessRegisteredServicePropertyList(rsps);
		
		StringBuffer buffer = new StringBuffer();
		List<RegisteredServiceProperty> warnRSPs = new ArrayList<RegisteredServiceProperty>();// 异常服务
		
		if (rsps != null) {
			buffer.append("Total Interface Number : " + rsps.size() + "\n");
			
			if (lined) {
				buffer.append(createRSStr("CTRLID", "ID", "ENDPOINT", "NAME"))
				       .append("\n");
				buffer.append("--------------------------------------------------\n");
			}
			
			int count = 0;
			for (RegisteredServiceProperty rsp : rsps) {
				if (lined) {
					Collection<Endpoint> es = rsp.getEndpoints();
					for (Endpoint e : es) {
						buffer.append(createRSStr(String.valueOf(rsp.getBundle().getBundleId()), 
								rsp.getId(), e.toString(), rsp.getName()))
						      .append("\n");
					}					
				} else {
					buffer.append(++count).append("\n")
					      .append("----------------------------------------\n")
						  .append(rsp)
						  .append("----------------------------------------\n");
				}
				
				if (rsp.getRs().getAttributes().getAttribute(FrameworkConstants.STREAM_LOG_NOT_WRITED) != null) {
					// 二进制日志记录功能已经被关闭
					warnRSPs.add(rsp);
				}
			}
			
			if (warnRSPs.size() > 0) {
				buffer.append("--------------------------------------------------\n");
				buffer.append("[WARN]:  STREAMLOG CLOSED FOR \n");
				for (RegisteredServiceProperty p : warnRSPs) {
					Collection<Endpoint> es = p.getEndpoints();
					for (Endpoint e : es) {
						buffer.append(createRSStr(String.valueOf(p.getBundle().getBundleId()), 
								p.getId(), e.toString(), p.getName()))
						      .append("\n");
					}
				}
			}			
		}
		
		return buffer.toString();
	}
	
	/**
	 * 显示格式化
	 * 
	 * @param controlId
	 * @param id
	 * @param endpoint
	 * @param name
	 * @return
	 */
	private static String createRSStr(String controlId, String id, String endpoint, String name) {
		String t = String.format("%6s    %-4s    %-20s    %s", controlId, id, endpoint, name);
		return t;
	}
	
	/**
	 * 详细描述
	 * 
	 * @param rsp
	 * @param properties
	 * @return
	 */
	public static String toStringDetail(RegisteredServiceProperty rsp, Map<String, String> properties) {
		StringBuffer buffer = new StringBuffer();
		buffer.append("----------------------------------------\n")
	          .append(rsp)
	          .append("[TASK DETAILS]:  \n")
	          .append(rsp.getTaskRecordStr());	          
	          
		if (properties != null) {
			buffer.append("[ETC]=").append(properties.remove("[ETC]")).append("\n");
			for (Iterator<String> itr = properties.keySet().iterator(); itr.hasNext();) {
				String name = itr.next();
				String value = properties.get(name);
				
				buffer.append(name).append("=").append(value).append("\n");
				
			}
		}
	    
	    buffer.append("----------------------------------------\n");
        
	    if (rsp.getRs() instanceof AbstractSocketService) {
	    	Collection<IoSession> sessions = ((AbstractSocketService)rsp.getRs()).getManagedSessions();
	    	buffer.append("[SESSIONS]:  \n\tsession number is: ")
	    	      .append(sessions.size()).append("\n")
	    	      .append(getSessionPrintStr(rsp.getBundle().getBundleId(), sessions))
	    	      .append("\n");
		    
		    buffer.append("----------------------------------------\n");
	    }
	    		
		return buffer.toString();
	}
	
	/**
	 * session描述
	 * 
	 * @param rsId
	 * @param sessions
	 * @return
	 */
	public static String getSessionPrintStr(long rsId, Collection<IoSession> sessions) {
		StringBuffer buffer = new StringBuffer();
		buffer.append("\t------------------------------\n");
		buffer.append("\t").append(formatSessionPrint("ID", "REMOTE_ADDR", "LOCAL_ADDR", "RECORD_ID")).append("\n");
		if (sessions != null) {	
			Map<String, IoSession> sessionsWithId = new LinkedHashMap<String, IoSession>();
			int i = 1;
			for (Iterator<IoSession> it = sessions.iterator(); it.hasNext(); i ++) {
				IoSession s = it.next();
				String sessionId = (String)s.getAttribute(FrameworkConstants.SESSION_ID_FOR_RS);
				if (sessionId != null) {
					sessionsWithId.put(sessionId, s);
					it.remove();
					buffer.append(createSessionDescFor(s, rsId, sessionId));
				}
			}
			
			i = 1;
			for (Iterator<IoSession> it = sessions.iterator(); it.hasNext(); i ++) {
				IoSession session = it.next();	
				
				String sessionId = String.valueOf(i);				
				while (sessionsWithId.get(sessionId) != null) {
					i ++;
					sessionId = String.valueOf(i);
				}
				
				session.setAttribute(FrameworkConstants.SESSION_ID_FOR_RS, sessionId);				
				buffer.append(createSessionDescFor(session, rsId, sessionId));				
			}
		}
				
		return buffer.toString();
	}
	
	/**
	 * 生成session描述
	 * 
	 * @param session
	 * @param rsId
	 * @param id
	 * @return
	 */
	private static String createSessionDescFor(IoSession session, long rsId, String id) {
		StringBuffer buffer = new StringBuffer();
		InterfaceLog intfLog = (InterfaceLog)session.getAttribute(FrameworkConstants.INTERFACE_LOG);				
		String recordId = intfLog != null ? intfLog.getRecordId() : "NULL";
		
		buffer.append("\t").append(formatSessionPrint(rsId + ":" + id, session.getRemoteAddress().toString(), 
		session.getLocalAddress().toString(), recordId)).append("\n");	
		
		return buffer.toString();
	}
	
	public static String formatSessionPrint(String id, String remoteAddr, String localAddr, String recordId) {
		String t = String.format("%8s    %20s    %20s    %s", id, remoteAddr, localAddr, recordId);
		
		return t;
	}

	public TaskRecord getTaskRecord() {
		return taskRecord;
	}

	public void setTaskRecord(TaskRecord taskRecord) {
		this.taskRecord = taskRecord;
	}

	public String getStartTime() {
		return startTime;
	}

	public void setStartTime(String startTime) {
		this.startTime = startTime;
	}

	public RegisteredService getRs() {
		return rs;
	}

	public void setRs(RegisteredService rs) {
		this.rs = rs;
	}

	public Bundle getBundle() {
		return bundle;
	}

	public void setBundle(Bundle bundle) {
		this.bundle = bundle;
	}

}
